package io.kimmking.rpcfx.proxy;

import com.alibaba.fastjson.JSON;
import io.kimmking.rpcfx.api.Filter;
import io.kimmking.rpcfx.api.LoadBalancer;
import io.kimmking.rpcfx.api.RpcfxRequest;
import io.kimmking.rpcfx.api.RpcfxResponse;
import io.kimmking.rpcfx.client.NettyClient;
import io.kimmking.rpcfx.context.RpcfxContext;
import io.kimmking.rpcfx.register.center.api.ProviderInfo;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;


/**
 * @author lfy
 */
public class CustomInterceptor implements MethodInterceptor {
    private final Class<?> serviceClass;
    private final Filter[] filters;
    private final LoadBalancer loadBalancer;
    private List<ProviderInfo> providers ;
    public CustomInterceptor(Class<?> serviceClass, LoadBalancer loadBalancer, Filter... filters) {
        this.serviceClass = serviceClass;
        this.filters = filters;
        this.loadBalancer = loadBalancer;
    }

    public void setProviders(List<ProviderInfo> providers) {
        this.providers = providers;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        String methodName = method.getName();
        String serviceClassName = this.serviceClass.getName();
        RpcfxResponse response = call(serviceClassName, methodName, args,filters,loadBalancer,providers);
        Class<?> returnType = method.getReturnType();
        return JSON.parseObject(response.getResult().toString(),returnType);
    }

    public static RpcfxResponse call(String serviceClassName,String methodName, Object[] args, Filter[] filters,LoadBalancer loadBalancer,List<ProviderInfo> providers){
        RpcfxRequest request = new RpcfxRequest();
        request.setServiceClass(serviceClassName);
        request.setMethod(methodName);
        request.setParams(args);
        if (null!=filters) {
            for (Filter filter : filters) {
                if (!filter.filter(request)) {
                    return null;
                }
            }
        }
        ProviderInfo providerInfo = loadBalancer.select(providers);
        String uri = providerInfo.getProtocol()+"://"+providerInfo.getHost()+":"+providerInfo.getPort();
        return post(request, uri);

    }

    private static RpcfxResponse post(RpcfxRequest req, String uri)  {

        String reqStr = JSON.toJSONString(req);

        System.out.println("req : "+reqStr);

        String respJson = NettyClient.getResponse(uri, reqStr);
        System.out.println("resp : "+respJson);
        //获取到消息后删除上下文
        RpcfxContext.clean();
        return JSON.parseObject(respJson,RpcfxResponse.class);
    }
}
